/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package cn.cloudbae.service;

import cn.cloudbae.Application;
import cn.cloudbae.listener.JobEventListener;
import cn.cloudbae.model.ResponseBody;

import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.dataflow.DataflowJobConfiguration;
import com.dangdang.ddframe.job.exception.JobSystemException;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.lifecycle.api.JobAPIFactory;
import com.dangdang.ddframe.job.lite.lifecycle.api.JobOperateAPI;
import com.dangdang.ddframe.job.lite.lifecycle.api.JobStatisticsAPI;
import com.dangdang.ddframe.job.lite.lifecycle.domain.JobBriefInfo;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.google.common.base.Optional;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Service;

@Service
public class JobLifeCycleService{
    
    @Value("${esjob.regCenter.serverList}")
    String zkServiceList;
    
    @Value("${esjob.regCenter.namespace}")
    String jobNamespace;
    
    @Autowired
    ZookeeperRegistryCenter zookeeperRegistryCenter;
    
    
    private static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";
    
    public void createBeanDefinitionBuilder(Class clazz,String beanName,Object [] args){
        //获取BeanFactory  
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) Application.applicationContext.getAutowireCapableBeanFactory();  
        //创建bean信息.  
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        if(args != null){
            for(int i = 0;i < args.length;i++){
                beanDefinitionBuilder.addConstructorArgValue(args[i]);
            }
        }
        defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
    }
    
    /**
     * 从Spring容器中移除bean
     * @param beanIdOrName 
     */
    public void unregisterBean(String beanIdOrName){
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) Application.applicationContext.getAutowireCapableBeanFactory();
        defaultListableBeanFactory.removeBeanDefinition(beanIdOrName);
    }
    
    /**
     * 根据名称和类型获取Bean实例
     * @param <T>
     * @param clazz
     * @param name
     * @return 
     */
    public <T>T getBean(Class<T> clazz,String name){
        return Application.applicationContext.getBean(name, clazz);
    }
    
    
    /**
     * 手动创建并调用任务
     * @param jobName
     * @param clazz
     * @param params
     * @param shardingItemParameters
     * @param totalCount
     * @param loadCron
     * @param description
     * @return channel + "_custom_or_fail_download_job_" + time
     */
    public ResponseBody scheludeJob(String jobName,final Class<? extends SimpleJob> clazz,Object [] params,int totalCount,String shardingItemParameters,String loadCron,String description){
        String loadName = jobName;
        createBeanDefinitionBuilder(clazz, loadName, params);
        SimpleJob simpleJob = (SimpleJob)getBean(clazz, loadName);
        createJob(simpleJob,loadName,loadCron,description, totalCount,shardingItemParameters);
        return new ResponseBody(true, 200, "任务创建成功！任务将在10秒后注册上去！");
    }
    
    /**
     * 获取所有任务
     * @return 
     */
    public Collection<JobBriefInfo> getJobList(){
        JobStatisticsAPI jobStatisticsAPI = JobAPIFactory.createJobStatisticsAPI(zkServiceList, jobNamespace, Optional.fromNullable(null));
        Collection<JobBriefInfo> jobInfos = jobStatisticsAPI.getAllJobsBriefInfo();
        return jobInfos;
    }
    
    /**
     * 删除指定任务
     * @param jobName
     * @return 
     */
    public ResponseBody removeJob(String jobName){
        if(zookeeperRegistryCenter.isExisted("/" + jobName)){
            JobOperateAPI jobOperateAPI = JobAPIFactory.createJobOperateAPI(zkServiceList, jobNamespace, Optional.fromNullable(null));
            jobOperateAPI.remove(Optional.of(jobName), Optional.<String>absent());
            zookeeperRegistryCenter.remove("/" + jobName);
            if(!zookeeperRegistryCenter.isExisted("/" + jobName))
                return new ResponseBody(true, 200, "删除任务成功");
            else
                return new ResponseBody(true, 500, "删除任务失败");
        }else
            return new ResponseBody(true, 404, "找不到指定任务");
        
    }
    
    /**
     * 删除崩溃任务
     * @return 
     */
    public ResponseBody removeCashedJobs(){
        Collection<JobBriefInfo> jobInfos = getJobList();
        for(JobBriefInfo job : jobInfos){
            if(job.getStatus().equals(JobBriefInfo.JobStatus.CRASHED)){
                removeJob(job.getJobName());
            }
        }
        return new ResponseBody(true, 200, "删除崩溃任务成功！");
    }
    
    /**
     * 动态创建定时任务
     * @param jobName 任务名称
     * @param job     任务实例   
     * @param cron    任务执行表达式
     * @param description
     * @param totalCount 分片总数
     * @param shardingItemParameters 分片逻辑
     * @return 
     */
    public boolean createJob(SimpleJob job,String jobName,String cron,String description,int totalCount,String shardingItemParameters) {
        LiteJobConfiguration liteJobConfiguration =  LiteJobConfiguration.newBuilder(new DataflowJobConfiguration(JobCoreConfiguration.newBuilder(
                jobName, cron, totalCount).description(description).jobParameter("Custom").shardingItemParameters(shardingItemParameters).build(), job.getClass().getCanonicalName(), false)).overwrite(true).build();
        SpringJobScheduler jobScheduler = new SpringJobScheduler(job, zookeeperRegistryCenter, liteJobConfiguration,new JobEventListener(zkServiceList,jobNamespace,zookeeperRegistryCenter,this));
        try {
            jobScheduler.init();
        }catch (JobSystemException e){
            e.printStackTrace();
            return false;
        }
        return true;
    }
    
    /***
     * @param date 时间
     * @return cron类型的日期
     */
    public static String getCron(final Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
        String formatTimeStr = "";
        if (date != null) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }
    
}
